﻿using System.Security.Cryptography;

namespace Koala.Pro.Common
{
    public class SequentialGuidGenerator : IGuidGenerator
    {
        private static readonly RandomNumberGenerator RandomNumberGenerator = RandomNumberGenerator.Create();

        public AbpSequentialGuidGeneratorOptions Options { get; set; }

        public SequentialGuidGenerator(AbpSequentialGuidGeneratorOptions options)
        {
            Options = options;
        }

        public Guid Create()
        {
            return Create(Options.GetDefaultSequentialGuidType());
        }

        public Guid Create(SequentialGuidType guidType)
        {
            byte[] array = new byte[10];
            RandomNumberGenerator.GetBytes(array);
            byte[] bytes = BitConverter.GetBytes(DateTime.UtcNow.Ticks / 10000);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse((Array)bytes);
            }
            byte[] array2 = new byte[16];
            switch (guidType)
            {
                case SequentialGuidType.SequentialAsString:
                case SequentialGuidType.SequentialAsBinary:
                    Buffer.BlockCopy(bytes, 2, array2, 0, 6);
                    Buffer.BlockCopy(array, 0, array2, 6, 10);
                    if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian)
                    {
                        Array.Reverse((Array)array2, 0, 4);
                        Array.Reverse((Array)array2, 4, 2);
                    }
                    break;
                case SequentialGuidType.SequentialAtEnd:
                    Buffer.BlockCopy(array, 0, array2, 0, 10);
                    Buffer.BlockCopy(bytes, 2, array2, 10, 6);
                    break;
            }
            return new Guid(array2);
        }
    }
}
